package com.team5101.client;


import com.team5101.client.handler.AccountClientHandler;
import com.team5101.config.RpcProperties;
import com.team5101.encode.RpcEncoder;
import com.team5101.model.RpcRequest;
import com.team5101.serializer.JSONSerializer;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Proxy;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;



@Component
public class RpcConsumer {

	@Autowired
	private RpcProperties rpcProperties;

	private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

	private AccountClientHandler accountClientHandler;

	//1.创建代理对象

	/**
	 * @param serviceClass 被调用的服务类
	 * @return
	 */
	public Object createProxy(final Class<?> serviceClass) {
		Object proxyInstance = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{serviceClass}, (proxy, method, args) -> {

			//2初始化客户端
			if (this.accountClientHandler == null) {
				initClient();
			}

			RpcRequest request = new RpcRequest();
			request.setRequestId(UUID.randomUUID().toString());
			request.setClassName(method.getDeclaringClass().getName());
			request.setMethodName(method.getName());
			request.setParameterTypes(method.getParameterTypes());
			request.setParameters(args);


			//3设置参数
			this.accountClientHandler.setPara(request);

			//请求服务端
			return executor.submit(this.accountClientHandler).get();
		});

		return proxyInstance;
	}


	public void initClient() throws InterruptedException {
		this.accountClientHandler = new AccountClientHandler();

		//
		EventLoopGroup eventExecutors = new NioEventLoopGroup();

		Bootstrap bootstrap = new Bootstrap();

		bootstrap.group(eventExecutors)
				.channel(NioSocketChannel.class)
				.option(ChannelOption.TCP_NODELAY, true)
				.handler(new ChannelInitializer<SocketChannel>() {
					@Override
					protected void initChannel(SocketChannel ch) throws Exception {
						ChannelPipeline pipeline = ch.pipeline();

						//对RpcRequest编码
						pipeline.addLast(new RpcEncoder(RpcRequest.class, new JSONSerializer()));
						//对RpcResponse解码
						//pipeline.addLast(new RpcDecoder(RpcResponse.class, new JSONSerializer()));
						pipeline.addLast(new StringDecoder());

						pipeline.addLast(accountClientHandler);
					}
				});

		//连接
		bootstrap.connect(rpcProperties.getHost(), rpcProperties.getPort()).sync();

	}


}
